package com.qbt.unipock.agent.dao.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.Query;
import javax.persistence.criteria.Predicate;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Repository;

import com.qbt.unipock.agent.dao.DistributorRepositoryCustom;
import com.qbt.unipock.agent.repository.DistributorRepository;
import com.xjoyt.pay.abstracts.AbstractDao;
import com.xjoyt.pay.dto.ExecuteResult;
import com.xjoyt.pay.dto.PageParam;
import com.xjoyt.pay.dto.PageResult;
import com.xjoyt.pay.master.params.DistributorOrderGroupParam;

import com.xjoyt.pay.merchant.register.params.DistributorPageParam;
import com.xjoyt.pay.master.po.Distributor;




public class DistributorRepositoryImpl extends AbstractDao implements DistributorRepositoryCustom {

	@Autowired
	private DistributorRepository repository;

	@Override
	public Distributor findOneByAccount(String account) {
		Page<Distributor> page=	repository.findAllByNoOrPhone(account, account, getFirstPageable());
		return page.hasContent() ? page.iterator().next() : null;
	}

	@Override
	public Distributor findOneByNo(String no) {
		Page<Distributor> page = repository.findAllByNo(no, getFirstPageable());
		return page.hasContent() ? page.iterator().next() : null;
	}

	@Override
	public Long getLastNo() {
		return repository.count();
	}

	@Override
	public PageResult<Distributor> loadPage(PageParam<DistributorPageParam> param) {
		Pageable pageable = getPageable(param);
		Specification<Distributor> spec = getSpecification(param.query);
		Page<Distributor> pageResult = repository.findAll(spec, pageable);

		return new PageResult<Distributor>(pageResult.getTotalElements(), pageResult.getContent());
	}

	private Specification<Distributor> getSpecification(DistributorPageParam param) {
		Specification<Distributor> spec = (root, query, cb) -> {
			List<Predicate> list = new ArrayList<>();
			if (param == null) {
				return null;
			}
			if (CollectionUtils.isNotEmpty(param.parentList)) {
				list.add(root.get("company").get("id").in(param.parentList));
			}

			if (StringUtils.isNotBlank(param.parentId)) {
				list.add(cb.or(cb.equal(root.get("company").get("id"), param.parentId),
						cb.like(root.get("company").get("path"), "%" + param.parentId + "%")));
			}

			if (StringUtils.isNotBlank(param.query)) {
				for (String string : param.query.split(" ")) {
					if (StringUtils.isBlank(string))
						continue;
					String like = "%" + string + "%";
					list.add(cb.or(cb.like(root.get("name"), like), cb.like(root.get("no"), like),
							cb.like(root.get("idNumber"), like)));
				}
			}

			if (param.status != null) {
				list.add(cb.equal(root.get("status"), param.status));
			}
			if (param.enabled != null) {
				list.add(cb.or(cb.equal(root.get("enabled"), param.enabled)));
			}
			if (CollectionUtils.isNotEmpty(list))
				query.where(cb.and(list.toArray(new Predicate[list.size()])));

			return null;
		};
		return spec;
	}

	@Override
	public List<Map<String, Object>> sum(List<String> ids, DistributorOrderGroupParam param) {
		StringBuilder builder = new StringBuilder(
				" select new map(a.merchant.distributor.id as id, sum(a.money) as sum, count(*) as count)from Order a where a.merchant.distributor.id in :ids ");
		Map<String, Object> params = new HashMap<>();
		params.put("ids", ids);
		if (param.startDate != null && param.endDate != null) {
			param.startDate = toStartDate(param.startDate);
			param.endDate = toEndDate(param.endDate);
			builder.append(" and ( a.addedDate between :startDate and :endDate ) ");
			params.put("startDate", param.startDate);
			params.put("endDate", param.endDate);
		}

		if (param.success != null) {
			builder.append(" and ( a.success = :success) ");

			params.put("success", param.success);
		}
		if (param.done != null) {
			builder.append(" and ( a.done = :done ) ");
			params.put("done", param.done);
		}

		builder.append(" group by a.merchant.distributor.id ");
		Query query = entityManager.createQuery(builder.toString());
		for (Entry<String, Object> entry : params.entrySet()) {
			query.setParameter(entry.getKey(), entry.getValue());
		}

		@SuppressWarnings("unchecked")
		List<Map<String, Object>> result = query.getResultList();
		return result;
	}

	

}
